package logic;

import java.util.List;
import java.util.LinkedList;

public class ConDiaCClass{
    private List<EBNFClass> ebnfs;
    private List<GLCClass> glcs;
    private List<Operation> operations;
    private boolean errores;
    private List<String> res, errors;
    
    public ConDiaCClass(){
		this.ebnfs=new LinkedList<EBNFClass>();
		this.glcs=new LinkedList<GLCClass>();
		this.operations=new LinkedList<Operation>();
		this.errores=false;
		this.res=new LinkedList<String>();
		this.errors=new LinkedList<String>();
    }

    public ConDiaCClass(List<EBNFClass> ebnfs, List<GLCClass> glcs, List<Operation> operations){
		this.ebnfs=ebnfs;
		this.glcs=glcs;
		this.operations=operations;
		this.errores=false;
		this.res=new LinkedList<String>();
		this.errors=new LinkedList<String>();
    }

    public boolean getErrores(){
    	return this.errores;
    }
    
    public void setErrores(boolean errores){
    	this.errores=errores;
    }
    
    public List<EBNFClass> getEBNFs(){
	return this.ebnfs;
    }

    public List<GLCClass> getGLCs(){
	return this.glcs;
    }

    public List<Operation> getOperations(){
	return this.operations;
    }

    public void addEBNF(EBNFClass e){
	this.ebnfs.add(e);
    }

    public void addGLC(GLCClass g){
	this.glcs.add(g);
    }

    public void addOperation(Operation o){
	this.operations.add(o);
    }

    public void addOperations(ConDiaCClass cdc){
	for(int i=0;i<cdc.getOperations().size();i++)
	    this.operations.add(cdc.getOperations().get(i));
    }
    
    public List<String> getRes(){
    	return this.res;
    }

    public List<String> getErroresOutput(){
    	return this.errors;
    }
    
    public boolean existsEBNF(String id){
    	boolean exists=false;
    	for(int e=0; e<ebnfs.size() && !exists;e++)
    		if(ebnfs.get(e).getId().equals(id))
    			exists=true;
    	return exists;
    }
    
    public boolean existsGLC(String id){
    	boolean exists=false;
    	for(int g=0; g<glcs.size() && !exists;g++)
    		if(glcs.get(g).getId().equals(id))
    			exists=true;
    	return exists;
    }

    public boolean existsSREBNF(String id, String domain){
    	boolean exists=false;
		for(int e=0; e<ebnfs.size() && !exists;e++)
			if(ebnfs.get(e).getId().equals(id))
				for(int s=0;s<ebnfs.get(e).getSimbols().size() && !exists;s++)
					if(ebnfs.get(e).getSimbols().get(s).equals(domain))
						exists=true;
		return exists;
    }
    
    public boolean existsSRGLC(String id, String domain){
    	boolean exists=false;
		for(int g=0; g<glcs.size() && !exists;g++)
			if(glcs.get(g).getId().equals(id))
				for(int s=0;s<glcs.get(g).getSimbols().size() && !exists;s++)
					if(glcs.get(g).getSimbols().get(s).equals(domain))
						exists=true;
		return exists;
    }
    
    public List<String> getConway(String id, String domain){
	String head="digraph finite_state_machine", indot=" {\nrankdir=LR;\nnode [shape=box];\n", tail="}";
	List<String> conways=new LinkedList<String>(), result=new LinkedList<String>();

	for(int i=0;i<ebnfs.size();i++){
	    if(ebnfs.get(i).getId().equals(id))
	       conways=ebnfs.get(i).getConway(domain);
	}

	for(int i=0;i<conways.size();i++)
	    result.add(head+i+indot+conways.get(i)+tail);

	return result;
    }
    /*
    @Override public String toString(){
	String sebnf="",sglc="",sop="";
	for(int i=0;i<getEBNFs().size();i++)
	    sebnf+=getEBNFs().get(i).toString();
	for(int i=0;i<getGLCs().size();i++)
	    sglc+=getGLCs().get(i).toString();
	for(int i=0;i<getOperations().size();i++)
	    sop+=getOperations().get(i).toString();
	return "EBNFs:\n"+sebnf+"GLCs:\n"+sglc+"Operations:\n"+sop;
    }
    */


    public void runOperations(){
		List<String> conways;
		res=new LinkedList<String>();
		for(int i=0; i<operations.size();i++){
		    if(operations.get(i).getType().equals("ebnf2conway")){
		    	conways=getConway(operations.get(i).getId(),operations.get(i).getDomain());
		    	for(int j=0;j<conways.size();j++){
		    		System.out.println(conways.get(j));
		    		res.add(conways.get(j));
		    	}
		    }
		    if(operations.get(i).getType().equals("glc2conway")){
		    	GLC2EBNF(operations.get(i).getId());
				conways=getConway(operations.get(i).getId(),operations.get(i).getDomain());
				for(int j=0;j<conways.size();j++){
			    	System.out.println(conways.get(j));
			    	res.add(conways.get(j));
				}
		    }
		    if(operations.get(i).getType().equals("glc2ebnf")){
				GLC2EBNF(operations.get(i).getId());
				for(int j=0;j<ebnfs.size();j++)
				    if(ebnfs.get(j).getId().equals(operations.get(i).getId())){
				       System.out.println(ebnfs.get(j).toString());
				       res.add(ebnfs.get(j).toString());
				    }
		    }	
		    if(operations.get(i).getType().equals("ebnf2glc")){
				EBNF2GLC(operations.get(i).getId());
				for(int j=0;j<glcs.size();j++)
				    if(glcs.get(j).getId().equals(operations.get(i).getId())){
				       System.out.println(glcs.get(j).toString());
				       res.add(glcs.get(j).toString());
				    }
			    }
		}
    }

    public void GLC2EBNF(String id){
		int indice=-1;
		for(int i=0;i<glcs.size();i++){
		    if(glcs.get(i).getId().equals(id)){
			indice=i;
		    }
		}
		if(indice!=-1){
			EBNFClass e = new EBNFClass(id, glcs.get(indice).getSimbols(), glcs.get(indice).GLC2EBNF());
		    addEBNF(e);
		    
		    /*
		    EBNFClass e = new EBNFClass(id);
		    for(int i=0;i<glcs.get(indice).getSimbols().size();i++)
		    	e.addSimbol(glcs.get(indice).getSimbols().get(i));
		    
		    for(int i=0;i<glcs.get(indice).getSintaxRule().size();i++)
		    	e.addSR(glcs.get(indice).getSintaxRule().get(i).GLC2EBNF());
		    */
			
		    //		e.setSR(glcs.get(indice).GLC2EBNF())
		}
		
		//	return glcs.get(indice).GLC2EBNF();
    }

    public void EBNF2GLC(String id){
		int indice=-1;
		for(int i=0;i<ebnfs.size();i++){
		    if(ebnfs.get(i).getId().equals(id)){
			indice=i;
		    }
		}
		
		if(indice!=-1){
		    GLCClass g = new GLCClass(id,ebnfs.get(indice).getSimbols(),ebnfs.get(indice).EBNF2GLC());
		    addGLC(g);
		    //		e.setSR(glcs.get(indice).GLC2EBNF())
		}
		
		//	return glcs.get(indice).GLC2EBNF();
	
    }
    
    public String toString(){
		String s="";
		for(int i=0;i<ebnfs.size();i++)s+=ebnfs.get(i).toString();
		for(int i=0;i<glcs.size();i++)s+=glcs.get(i).toString();
		
		return s;
    }	
}